﻿using System;
using System.IO;
using System.Threading.Tasks;

using iTool.ClusterComponent;

using Microsoft.Data.Sqlite;

using Orleans;
using Orleans.Concurrency;
using Orleans.Runtime;

namespace iTool.Cloud.Database.ServiceProvider
{
    /// <summary>
    /// 1 文件库
    /// 2 文件碎片库 => 文件库
    /// </summary>
    [ClusterPlacementStrategy]
    [Reentrant]
    public class FileExistsService : iToolServiceBase, iFileExistsService
    {
        readonly ISiloStatusOracle siloStatusOracle;
        const string DirectoryPath = "./Upload";
        const string DataSource = DirectoryPath + "/Upload.files";
        const string IniSql = "CREATE TABLE IF NOT EXISTS FileList(key varchar PRIMARY KEY, User varchar, Role varchar, SuffixName any,ContentType any,UploadState int, TotalLength long, FileStream any,CreateDate any)";
        //const string DataPieceSource = DirectoryPath + "/Upload.pieces";
        string connectionString = string.Empty;
        //string connectionStringOfPiece = string.Empty;
        string FileID { get; set; }
        int UploadState { get; set; } = -1;

        public FileExistsService(ISiloStatusOracle siloStatusOracle)
        {
            if (!Directory.Exists(DirectoryPath))
                Directory.CreateDirectory(DirectoryPath);
            this.siloStatusOracle = siloStatusOracle;
        }

        public async override Task OnActivateAsync()
        {
            this.FileID = this.GetPrimaryKeyString();
            if (this.FileID.IndexOf('/') > -1)
            {
                this.FileID = this.FileID.Split('/')[1];
            }
            this.connectionString = new SqliteConnectionStringBuilder
            {
                DataSource = DataSource,
                Mode = SqliteOpenMode.ReadWriteCreate,
                Cache = SqliteCacheMode.Shared,
                Pooling = true
            }.ToString();

            //command.CommandText = $"CREATE INDEX FilePieceList_key on FilePieceList(key)";
            //SELECT 1 FROM sqlite_master WHERE type = 'index' and name = 'FilePieceList_key';

            using (var connection = new SqliteConnection(this.connectionString))
            {
                connection.Open();
                using (SqliteCommand command = new SqliteCommand(IniSql, connection))
                {
                    command.ExecuteNonQuery();
                }
            }

            this.LoadUploadState();

            await base.OnActivateAsync();
        }

        void LoadUploadState()
        {
            using (var connection = new SqliteConnection(this.connectionString))
            {
                connection.Open();
                var selectCommand = connection.CreateCommand();
                selectCommand.CommandText = @"select UploadState from FileList where key=$key";
                selectCommand.Parameters.AddWithValue("$key", this.FileID);
                var reader = selectCommand.ExecuteReader();
                while (reader.Read())
                {
                    this.UploadState = reader.GetInt32(0);
                }
            }
        }

        public Task<int> IsExistsAsync()
        {
            if (this.UploadState < 200)
            {
                this.LoadUploadState();
            }
            return Task.FromResult(this.UploadState);
            //return Task.FromResult(this.UploadState > -1);
        }

        public async Task AcceptNotificationSyncFileDataAsync(string siloAddress)
        {
            // 本地激活，并且开始同步
            var service = this.GrainFactory.GetGrain<iFileService>(string.Format("{0}/{1}", siloStatusOracle.SiloAddress.ToParsableString(), this.FileID));
            await service.CopyFileAsync(siloAddress);
        }

        public async Task AcceptNotificationDaleteFileDataAsync()
        {
            // 本地激活，开始删除
            var service = this.GrainFactory.GetGrain<iFileService>(string.Format("{0}/{1}", siloStatusOracle.SiloAddress.ToParsableString(), this.FileID));
            await service.DeleteFileAsync();
        }
    }
}
